# 导入
#from django.db import models
#from django.contrib.auth.models import AbstractUser

# 我们重写用户模型类, 继承自 AbstractUser
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
from itsdangerous import TimedJSONWebSignatureSerializer, BadData

from huamei_mall.utils.BaseModel import BaseModel


class User(AbstractUser):
    """自定义用户模型类"""

    # 额外增加 mobile 字段

    mobile = models.CharField(max_length=11,
                              unique=True,
                              verbose_name='手机号')

    email_active = models.BooleanField(default=False,
                                       verbose_name='邮箱状态认证')

    default_address = models.ForeignKey('Address',
                                        related_name='users',
                                        null=True,
                                        blank=True,
                                        on_delete=models.SET_NULL,
                                        verbose_name='默认地址')

    # 对当前表进行相关设置:
    class Meta:
        db_table = 'tb_users'
        verbose_name = '用户'
        verbose_name_plural = verbose_name

    # 在 str 魔法方法中, 返回用户名称
    def __str__(self):
        return self.username


    '''生成邮箱验证链接'''
    def generate_verify_email_url(self):
        # 邮件验证码有效期: 1天
        serializer = TimedJSONWebSignatureSerializer(settings.SECRET_KEY,
                                            expires_in=60 * 60 * 24)
        # 拼接参数
        data = {'user_id':self.id,'user_email':self.email}
        # 加密生成 token 值, 这个值是 bytes 类型, 所以解码为 str:
        token = serializer.dumps(data).decode()

        verify_url = settings.EMAIL_VERIFY_URL + token
        return verify_url

    # JWT协议似乎已经应用十分广泛，JSON Web Token——一种基于token的json格式web认证方法。
    # 基本的原理是，第一次认证通过用户名密码，服务端签发一个json格式的token。
    # 后续客户端的请求都携带这个token，服务端仅需要解析这个token，来判别客户端的身份和合法性。
    # serializer 存储了序列化的secreate key和salt key。
    # genTokenSeq这个函数用于生成token。其中使用的是TimedJSONWebSignatureSerializer进行序列的生成, 这里secret_key密钥、salt盐值从配置.
    # 调用函数生成秘钥序列，并设置有效期


    # 定义验证函数:
    @staticmethod
    def check_verify_email_token(token):
        """
        验证token并提取user
        :param token: 用户信息签名后的结果
        :return: user, None
        """
        # 调用 itsdangerous 类,生成对象
        # 邮件验证链接有效期：一天
        serializer = TimedJSONWebSignatureSerializer(settings.SECRET_KEY,
                                                     expires_in=60 * 60 * 24)
        try:
            # 解析传入的 token 值, 获取数据 data
            data = serializer.loads(token)
        except BadData:
            # 如果传入的 token 中没有值, 则报错
            return None
        else:
            # 如果有值, 则获取
            user_id = data.get('user_id')
            email = data.get('user_email')

            # 获取到值之后, 尝试从 User 表中获取对应的用户
        try:
            user = User.objects.get(id=user_id,
                                    email=email)
        except Exception as e:
            # 如果用户不存在, 则返回 None
            return None
        else:
            # 如果存在则直接返回
            return user



class Address(BaseModel):
    # 参数self写成了User，意思是关联模型类User对应表。也可以关联自己；
    user = models.ForeignKey(User,
    #第二行 on_delete=models.CASCADE。
    #主外关系键中，级联删除，也就是当删除主表的数据时候从表中的数据也随着一起删除
                             on_delete=models.CASCADE,
                             # related_name 指明查询一个行政区划的所有下级行政区划时
                             #使用 Address模型类.addresser 语法查询
                             related_name= 'addresses',
                             verbose_name= '用户'
                             )
    # 参数self写成了areas.Area，意思是关联areas.Area模型类对应的表。也可以关联自己；
    province = models.ForeignKey('areas.Area',
                                 on_delete=models.PROTECT,
                                 related_name='province_addresses',
                                 verbose_name='省')

    city = models.ForeignKey('areas.Area',
                             on_delete=models.PROTECT,
                             related_name='city_addresses',
                             verbose_name='市')

    district = models.ForeignKey('areas.Area',
                                 on_delete=models.PROTECT,
                                 related_name='district_addresses',
                                 verbose_name='区')

    title = models.CharField(max_length=20,verbose_name='标题')
    receiver = models.CharField(max_length=20,verbose_name='收货人')
    place = models.CharField(max_length=50,verbose_name='收货地址')
    mobile = models.CharField(max_length=11,verbose_name='手机号')
    tel = models.CharField(max_length=20,
                           null=True,
                           blank=True,
                           default='',
                           verbose_name='固定电话')

    email = models.CharField(max_length=30,
                             null=True,
                             blank=True,
                             default='',
                             verbose_name='电子邮箱')
    is_deleted = models.BooleanField(default=False,verbose_name='逻辑删除')

    class Meta:

        db_table = 'tb_address'
        verbose_name = '收货地址'
        verbose_name_plural = verbose_name
        # 地址随更新时间随之往后移动
        ordering = ['-update_time']